# ShaBa - Set of utilies for easy backups.
# Copyright (C) 2012 Damien Vincent
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

import argparse
import hashlib
import os.path
import os
import shutil
import signal
import sys

FILENAME_SHA1_SIZE = 40


stop_backup = 0
def sigint_handler(signal, frame):
  sys.stderr.write('Interrupting backup...\n')
  stop_backup = 1


# Verify that the directory is a directory that contains only hash files.
# => No subdirectories or other files.
def is_hash_dir(dirname):
  for root, sub_folders, files in os.walk(dirname):
    if sub_folders:
      return 0
    for f in files:
      if len(f) != FILENAME_SHA1_SIZE:
        return 0
  return 1

# Remove orphans from a hash directory.
def remove_orphan(backup_dir_hash):
  for root, sub_folders, files in os.walk(backup_dir_hash):
    if sub_folders:
      sys.stderr.write('Error: Hash directory has sub-directories.\n');
      return
    for f in files:
      if len(f) != FILENAME_SHA1_SIZE:
        sys.stderr.write('Error: Some files are not hash files.\n');
        return
      filename_hash = os.path.join(backup_dir_hash, f)
      s = os.stat(filename_hash)
      if s.st_nlink == 1:
        # This file is referenced only in the hash directory
        # => it is an orphan => remove it.
        sys.stderr.write('Remove: ' + f + '\n')
        os.remove(filename_hash);
  return 1


def main():
  signal.signal(signal.SIGINT, sigint_handler)

  parser = argparse.ArgumentParser(description='Remove orphan from a hash directory.')
  parser.add_argument('--hash', action="store", dest="backup_dir_hash",
                      help='Hash directory')
  args = parser.parse_args()

  backup_dir_hash = args.backup_dir_hash

  sys.stderr.write('Step #1: Checking directories\n')
  if not is_hash_dir(backup_dir_hash):
    sys.stderr.write('Error: Hash directory contains some sub directories or common files\n')
    sys.exit(1)

  sys.stderr.write('Step #2: Looking for orphans\n')
  remove_orphan(backup_dir_hash)

if __name__ == "__main__":
  main()
